﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Htx.Rbmq.ConsumerApp1
{
    class Receive1
    {

        static void Main(string[] args)
        {
            //M1();
            //M2();
            //M3();
            //M4();
            M5();
        }

        /// <summary>
        /// 基础
        /// </summary>
        private static void M1()
        {
            var factory = new ConnectionFactory { HostName = "81.68.253.181", UserName = "admin", Password = "000000" };
            using var conn = factory.CreateConnection();
            using var channel = conn.CreateModel();
            channel.QueueDeclare(
                    queue: "hello",
                    durable: false,
                    exclusive: false,
                    autoDelete: false,
                    arguments: null
                );
            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, e) =>
            {
                var message = Encoding.UTF8.GetString(e.Body.ToArray());
                Console.WriteLine("[x] recevice {0}", message);
            };
            channel.BasicConsume(
                    queue: "hello",
                    autoAck: true,
                    consumer: consumer
                );
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();

        }

        /// <summary>
        /// 工作队列
        /// </summary>
        private static void M2()
        {
            var factory = new ConnectionFactory { HostName = "81.68.253.181", UserName = "admin", Password = "000000" };
            using var conn = factory.CreateConnection();
            using var channel = conn.CreateModel();
            channel.QueueDeclare(
                    queue: "task_queue",
                    durable: true,
                    exclusive: false,
                    autoDelete: false,
                    arguments: null
                );
            channel.BasicQos(0, 1, false);              // prefetchCount = 1，告诉rabbitmq，在消息还没有处理完成，返回确认消息之前，不要再发送下一条消息
            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, e) =>
            {
                var message = Encoding.UTF8.GetString(e.Body.ToArray());
                Console.WriteLine("[x] recevice {0}", message);
                Thread.Sleep(1000);
                channel.BasicAck(e.DeliveryTag, false); // 消息处理完成后回复rabbitmq
            };
            channel.BasicConsume(
                    queue: "task_queue",
                    autoAck: false,                     // 接到消息，不自动回复
                    consumer: consumer
                );
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();

        }

        /// <summary>
        /// 发布订阅
        /// </summary>
        private static void M3()
        {
            var factory = new ConnectionFactory { HostName = "81.68.253.181", UserName = "admin", Password = "000000" };
            using var conn = factory.CreateConnection();
            using var channel = conn.CreateModel();
            channel.ExchangeDeclare("logs", ExchangeType.Fanout);                       // 创建扇形交换机
            var queue = channel.QueueDeclare();                                         // 创建临时队列
            channel.QueueBind(queue.QueueName, "logs", "");                             // 将临时队列与交换机绑定
            var consumer = new EventingBasicConsumer(channel);                          // 创建消费者
            consumer.Received += (model, e) =>                                          // 接收来自队列的任务
            {
                Console.WriteLine("收到消息：{0}", Encoding.UTF8.GetString(e.Body.ToArray()));
                channel.BasicAck(e.DeliveryTag, false);
            };
            channel.BasicConsume(queue.QueueName, false, consumer);                     // 消费者绑定创建的临时队列

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }

        /// <summary>
        /// 路由子集（通过直连交换机，将指定路由键的消息发送到对应的队列）
        /// </summary>
        private static void M4()
        {
            var factory = new ConnectionFactory { HostName = "81.68.253.181", UserName = "admin", Password = "000000" };
            using var conn = factory.CreateConnection();
            using var channel = conn.CreateModel();
            channel.ExchangeDeclare("sky", ExchangeType.Direct);                        // 创建直连交换机
            var queue = channel.QueueDeclare();                                         // 创建临时队列
            var list = new List<string> { "red", "black", "orange", "blue" };           // 创建一个颜色列表
            var color1 = list[new Random().Next(0, 4)];
            var color2 = list[new Random().Next(0, 4)];
            channel.QueueBind(queue.QueueName, "sky", color1);                          // 将临时队列绑定路由键
            channel.QueueBind(queue.QueueName, "sky", color2);                          // 将临时队列绑定第二个路由键
            var consumer = new EventingBasicConsumer(channel);                          // 创建消费者
            consumer.Received += (model, e) =>                                          // 接收来自队列的任务
            {
                Console.WriteLine("收到消息：{0}", Encoding.UTF8.GetString(e.Body.ToArray()));
                channel.BasicAck(e.DeliveryTag, false);
            };
            channel.BasicConsume(queue.QueueName, false, consumer);                     // 消费者绑定创建的临时队列
            Console.WriteLine("绑定的路由键：{0} {1}", color1, color2);
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }

        /// <summary>
        /// 主题交换机
        /// </summary>
        private static void M5()
        {
            var factory = new ConnectionFactory
            { HostName = "81.68.253.181", UserName = "admin", Password = "000000"/*, VirtualHost = "my_vhost"*/ };
            using var conn = factory.CreateConnection();
            using var channel = conn.CreateModel();
            channel.ExchangeDeclare("animal", ExchangeType.Topic);                  // 创建一个主题交换机

            var animals = new List<string> { "dog", "cat", "monkey", "*" };              // 创建一个动物列表
            var colors = new List<string> { "red", "black", "white", "*" };              // 创建一个颜色列表
            var speeds = new List<string> { "100", "200", "300", "*" };                  // 创建一个速度列表

            var rdm = new Random();
            var key = $"{animals[rdm.Next(0, 4)]}.{colors[rdm.Next(0, 4)]}.{speeds[rdm.Next(0, 4)]}";
            var queueName = channel.QueueDeclare().QueueName;
            channel.QueueBind(queueName, "animal", key);

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, e) =>
            {
                Console.WriteLine(Encoding.UTF8.GetString( e.Body.ToArray()) + $"   我的路由键：{key}");
                channel.BasicAck(e.DeliveryTag, false);
            };

            channel.BasicConsume(queueName, false, consumer);
            Console.WriteLine("绑定的路由键：{0}", key);
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }

    }
}
